package com.shoy.myapp.common.task;

import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Looper;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Toast;

import com.shoy.myapp.BuildConfig;
import com.shoy.myapp.app.AppContext;
import com.shoy.myapp.app.AppManager;
import com.shoy.myapp.app.Constants;
import com.shoy.myapp.common.Utils;
import com.shoy.myapp.ui.DlgFrgProgress;
import com.shoy.myapp.ui.Login;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;
import java.util.*;

/**
 * 接口请求通用类
 * Created by shoy on 2014/9/4.
 */
public class ApiTask extends AsyncTask<Object, Void, JSONObject> {
    protected static final String TAG = "ApiTask";

    protected String httpMethod = Constants.HTTP_GET;
    protected boolean isCache = false;
    protected boolean isShow = true;
    protected boolean isCancel = true;
    protected boolean isCustomTip = false;
    protected Context mContext;
    protected DlgFrgProgress dialogFragment;

    private static long tick = 0;
    private static long lastTime;

    public ApiTask(Context mContext) {
        this.mContext = mContext;
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();
    }


    @Override
    protected void onPreExecute() {
        if (!isShow)
            return;
        dialogFragment = DlgFrgProgress.getInstance(isCancel);
        try {
            dialogFragment.show(((FragmentActivity) mContext)
                    .getSupportFragmentManager(), "loading");
        } catch (IllegalStateException e) {
            // ignore
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected JSONObject doInBackground(Object... params) {
        getTimeTask();
        JSONObject result = null;
        if (BuildConfig.DEBUG) {
            for (Object param : params) {
                Log.d(TAG, "" + param);
            }
        }
        if (params == null || params.length == 0)
            return null;
        SortedMap<String, String> mapParam = (SortedMap<String, String>) params[0];
//            mapParam.put("token",Constants.LOGIN_TOAKEN);//新增参数token
        mapParam.put("tick", Long.toString(tick));//新增参数tick
        StringBuffer sb = new StringBuffer();
        String sign = Utils.signParam(mapParam, sb);
        boolean isPost = Constants.HTTP_POST.equalsIgnoreCase(httpMethod);
        isCache = isCache && !isPost;
        String requestUrl = Constants.REST_SERVER;
        AppContext app = AppManager.getInstance().getApp();
        if (isPost) {
            mapParam.put("partner", Constants.PARTNER);
            mapParam.put("sign", sign);
        } else {
            sb.append("partner=").append(Constants.PARTNER).append("&sign=").append(sign);
            requestUrl += "?" + sb.toString();
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "requestUrl:" + requestUrl);
            }
            // 如果是Get并且设置缓存
            if (isCache) {
                result = app.getJson(requestUrl);
                if (result != null) {
                    Log.i(TAG, requestUrl + " from cache");
                    return result;
                }
            }
        }
        HttpClient client = HttpConnectionManager.getHttpClient();
        HttpUriRequest httpRequest = isPost ? new HttpPost(requestUrl) : new HttpGet(requestUrl);

        try {
            if (isPost) {
                List<NameValuePair> paramList = new ArrayList<NameValuePair>();
                Set<Map.Entry<String, String>> entrySet = mapParam.entrySet();
                for (Map.Entry<String, String> entry : entrySet) {
                    paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                ((HttpPost) httpRequest).setEntity(new UrlEncodedFormEntity(paramList, "utf-8"));
            }
            String bodyStr = HttpConnectionManager.parseBodyAsString(client, httpRequest);
            result = JSON.parseObject(bodyStr);

            // 如果是Get并且设置缓存加进缓存
            if (isCache) {
                Log.i(TAG, requestUrl + " set cache");
                app.setJson(requestUrl, result);
            }
        } catch (IOException e) {
            Log.e(TAG, "网络异常", e);
            // XXX 在异步线程中调用UI组件，必须在Looper.prepare() 和 Looper.loop()中调用
            Looper.prepare();
            Toast.makeText(mContext, "网络异常", Toast.LENGTH_SHORT).show();
            if (dialogFragment != null)
                dialogFragment.dismissAllowingStateLoss();
            Looper.loop();
            result = null;
        } catch (JSONException e) {
            Log.e(TAG, "JSON转换异常", e);
            Looper.prepare();
            Toast.makeText(mContext, "json转换异常", Toast.LENGTH_SHORT).show();
            if (dialogFragment != null)
                dialogFragment.dismissAllowingStateLoss();
            Looper.loop();
            result = null;
        } finally {
            httpRequest.abort();
        }
        return result;
    }

    @Override
    protected void onPostExecute(JSONObject result) {
        if (isCancelled()) {
            return;
        }
        if (dialogFragment != null)
            dialogFragment.dismissAllowingStateLoss();
        if (result != null && !isCustomTip) {
            boolean status;
            try {
                if (result.getBoolean(Constants.RESULT_STATUS) == null) {
                    Intent intent = new Intent(mContext, Login.class);
                    intent.putExtra("login_code", "调用目标发生异常，请检测网络连接后重新登录!");
                    intent.putExtra("is_login", "false");
                    mContext.startActivity(intent);
                    System.exit(0);
                } else {
                    status = result.getBoolean(Constants.RESULT_STATUS);
                    int code = result.getIntValue(Constants.RESULT_CODE);
                    String desc = result.getString(Constants.RESULT_DESC),
                            msg = result.getString(Constants.RESULT_MSG);
                    if (!status) {
                        if (code == 10011 || (code == -1 && desc.equals("登录超时，请重新登录！")) || desc.equals("登录邮箱尚未注册！")) {
                            Toast.makeText(mContext, desc, Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(mContext, Login.class);
                            intent.putExtra("is_login", "false");
                            intent.putExtra("login_code", desc);
                            mContext.startActivity(intent);
                            System.exit(0);
                        } else {
                            Log.e(Constants.TAG, "msg=" + msg + ",desc=" + desc);
                            Toast.makeText(mContext, desc, Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            } catch (JSONException e) {
                Log.e(Constants.TAG, "JSON转换异常", e);
            }
        }
    }

    /**
     * 获取到服务器上的时间戳
     */
    public void getTimeTask() {
        if (tick > 0) {
            long tickNow = System.currentTimeMillis();
            tick += (tickNow - lastTime) * 10000;
            lastTime = tickNow;
            Log.d(TAG, "缓存Tick:" + tick);
            return;
        }
        try {
            HttpResponse httpResponse;
            HttpGet httpGet = new HttpGet(Constants.TICKS_SERVER);
            httpResponse = new DefaultHttpClient().execute(httpGet);

            int status = httpResponse.getStatusLine().getStatusCode();
            if (status != 200) {
                throw new IOException("Post failed with error code " + status);
            }
            tick = Long.parseLong(EntityUtils.toString(httpResponse.getEntity()));
            lastTime = System.currentTimeMillis();
            Log.d(TAG, "服务器当前Tick:" + tick);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setCache(boolean cache) {
        isCache = cache;
    }


    public void Cancle() {
        isCancel = true;
    }


    public void setHttpMethod(String httpMethod) {
        this.httpMethod = httpMethod;
    }


    public void setShow(boolean show) {
        isShow = show;
    }


    public void setCustomTip(boolean customTip) {
        isCustomTip = customTip;
    }
}
